/**
 * 
 */
package com.devmindset.jpatoolbox;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.collections.Unmodifiable;
import org.apache.commons.collections.iterators.UnmodifiableIterator;
import org.apache.commons.collections.iterators.UnmodifiableListIterator;
import org.apache.commons.collections.list.AbstractSerializableListDecorator;

/**
 * Read-only list.
 * 
 * Will throw an {@link UnsupportedOperationException} on modify attempt.
 * 
 * @author <a href="mailto:ice.penov@devmindset.com">Ice Penov</a>
 */
@SuppressWarnings("unchecked")
public class ReadOnlyModelList extends AbstractSerializableListDecorator implements Unmodifiable {

  private static final long serialVersionUID = 3619907172543364531L;
  
  public static final String ERROR_MESSAGE = "Can't modify fetched domain list, because of bi-directional wiring issues. Please use the add{Entity}, remove{Entity} or set{EntityList} methods";

  /**
   * Factory method to create an unmodifiable list.
   * 
   * @param list  the list to decorate, must not be null
   * @throws IllegalArgumentException if list is null
   */
  public static List decorate(List list) {
      if (list instanceof Unmodifiable) {
          return list;
      }
      return new ReadOnlyModelList(list);
  }
  
  /**
   * Constructor that wraps (not copies).
   * 
   * @param list  the list to decorate, must not be null
   * @throws IllegalArgumentException if list is null
   */
  protected ReadOnlyModelList(List list) {
    super(list);
  }
  
  //-----------------------------------------------------------------------
  public Iterator iterator() {
      return UnmodifiableIterator.decorate(getCollection().iterator());
  }

  public boolean add(Object object) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public boolean addAll(Collection coll) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public void clear() {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public boolean remove(Object object) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public boolean removeAll(Collection coll) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public boolean retainAll(Collection coll) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  //-----------------------------------------------------------------------
  public ListIterator listIterator() {
      return UnmodifiableListIterator.decorate(getList().listIterator());
  }

  public ListIterator listIterator(int index) {
      return UnmodifiableListIterator.decorate(getList().listIterator(index));
  }

  public void add(int index, Object object) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public boolean addAll(int index, Collection coll) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public Object remove(int index) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public Object set(int index, Object object) {
      throw new UnsupportedOperationException(ERROR_MESSAGE);
  }

  public List subList(int fromIndex, int toIndex) {
      List sub = getList().subList(fromIndex, toIndex);
      return new ReadOnlyModelList(sub);
  }
  

}
